package com.beta.service.impl;

import com.beta.em.order.OrderStatus;
import com.beta.em.order.PayStatus;
import com.beta.entity.Orders;
import com.beta.entity.Shipments;
import com.beta.mapper.OrdersMapper;
import com.beta.service.IOrderStatusService;
import com.beta.service.IOrdersService;
import com.beta.service.IDateTimeService;
import com.beta.service.IShipmentsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Date;
import java.util.Objects;

/**
 * Created by vector on 2016/12/7.
 */
@Service
public class OrderStatusService implements IOrderStatusService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private IOrdersService ordersService;
    @Autowired
    private IDateTimeService dateTimeService;
    @Autowired
    private IShipmentsService shipmentsService;
    @Autowired
    private OrdersMapper ordersMapper;

    @Value("${order.expire.minutes}")
    private Long orderExpireMinutes;

    @Override
    public void changeStatus(Integer orderId, OrderStatus status, PayStatus payStatus) {
        logger.info("订单状态改变 ==> status -> {}, pay_status -> {}", status != null ? status.getValue() : "", payStatus != null ? payStatus.getValue() : "");
        Orders ordersForUpdate = new Orders().setId(orderId).setUpdatedAt(dateTimeService.toDbDate());
        if (Objects.nonNull(status)) {
            ordersForUpdate.setStatus(status.getValue());
        }
        if (Objects.nonNull(payStatus)) {
            ordersForUpdate.setPayStatus(payStatus.getValue());
        }
        ordersService.updateSelectiveById(ordersForUpdate);
    }

    @Override
    public void executeSyncExpiredOrderStatus() {
        // 条件为 now() - created_at > orderExpiredMinutes
        Date expiredMinCreateDate = Date.from(dateTimeService.toDbDate().toInstant().minus(Duration.ofMinutes(orderExpireMinutes)));
        ordersMapper.updateExpiresOrderStatusByCreatedAt(expiredMinCreateDate);
    }

    @Override
    public boolean isExpired(Orders order) {
        if (OrderStatus.EXPIRED.getValue().equals(order.getStatus())) {
            return true;
        }

        Date dbDateNow = dateTimeService.toDbDate();
        Date orderCreatedAt = order.getCreatedAt();
        Date expiredAt = order.getExpiredAt();
        if (Objects.isNull(expiredAt)) {
            expiredAt = Date.from(orderCreatedAt.toInstant().minus(Duration.ofMinutes(orderExpireMinutes)));
        }
        if (!expiredAt.after(dbDateNow)) {
            changeStatus(order.getId(), OrderStatus.EXPIRED, null);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean isCanceled(Orders orders) {
        return OrderStatus.CANCELED.getValue().equals(orders.getStatus());
    }

    @Override
    public boolean isPaid(Orders orders) {
        PayStatus payStatus = PayStatus.getPayStatus(orders.getPayStatus());
        return PayStatus.PAID.equals(payStatus) || PayStatus.FREIGHT_PAID.equals(payStatus);
    }

    @Override
    public boolean isAssigned(Orders orders) {
        Shipments shipment = shipmentsService.getShipmentByOrderId(orders.getId());
        return Objects.nonNull(shipment) && Objects.nonNull(shipment.getCourierId());
    }

    @Override
    public boolean isPicked(Orders orders) {
        Shipments shipment = shipmentsService.getShipmentByOrderId(orders.getId());
        return shipment != null && shipment.getPickedAt() != null;
    }

    @Override
    public boolean isShipped(Orders orders) {
        Shipments shipment = shipmentsService.getShipmentByOrderId(orders.getId());
        return shipment != null && shipment.getShippedAt() != null;
    }

    @Override
    public boolean isReceipted(Orders orders) {
        OrderStatus orderStatus = OrderStatus.getOrderStatus(orders.getStatus());
        switch (orderStatus) {
            case CONFIRMED:
            case COMPLETED:
            case SETTLED:
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean isComplete(Orders orders) {
        OrderStatus orderStatus = OrderStatus.getOrderStatus(orders.getStatus());
        switch (orderStatus) {
            case COMPLETED:
            case SETTLED:
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean isSettled(Orders orders) {
        OrderStatus orderStatus = OrderStatus.getOrderStatus(orders.getStatus());
        switch (orderStatus) {
            case SETTLED:
                return true;
            default:
                return false;
        }
    }
}
